﻿using IPluginInterface;
using Qting.SPI.Serialize;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using YiNing.Tools;

namespace Xinken
{
    [Serializable]
    public class MesPlugin : MarshalByRefObject, ISpiPlugin
    {
        public string Tag
        {
            get;
            private set;
        }

        public Version Version
        {
            get;
            private set;
        }

        public string Description
        {
            get;
            private set;
        }

        List<KeyValuePair<string, string>> guidList = new List<KeyValuePair<string, string>>();

        private HttpHelper httpHelper = new HttpHelper();
        private XinkenArgs xinkenArgs = new XinkenArgs();
        public MesPlugin()
        {
            Tag = "信垦SPI MES插件";
            Version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
            Description = "信垦SPI MES插件";
        }

        /// <summary>
        /// 通用接口,信垦的用来写如测试数据
        /// </summary>
        /// <param name="spiPcbs"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public PluginResult YiNing(ref SpiPcbs spiPcbs, params object[] args)
        {
            string fileName = DateTime.Now.ToString("yyyy-MM-dd HHmmssfff") + ".zyn";
            fileName = args.Length == 0 ? fileName : Path.Combine(args[0].ToString(), fileName);
            JsonHelper.Serialize(spiPcbs, fileName);
            return new PluginResult();
        }

        public PluginResult Init(params object[] args)
        {
            xinkenArgs = XinkenArgs.LoadThis();
            return new PluginResult();
        }

        public PluginResult Start(ref SpiPcbs SpiPcbs, bool bDual = false, params object[] args)
        {
            Log("Start");
            return new PluginResult();
        }

        public PluginResult BeforeProductIn(ref SpiPcbs SpiPcbs, bool bDual = false, params object[] args)
        {
            Log("BeforeProductIn");
            return new PluginResult();
        }
        public PluginResult ProductIn(ref SpiPcbs SpiPcbs, bool bDual = false, params object[] args)
        {
            Log("ProductIn");
            /*
                1.H_ACTION的值改成SPI；G_STATION，G_WS改成相应的SPI站位SPI_B或SPI_T
                2.MesCheckFlow和MesUpdateInfo增加几个字段回传：
                》G_SIDE：面别（B或者T）
                》G_StencilSN：钢网编号 
                》G_SqueegeeSN：刮刀编号 
                》G_SPSN：锡膏编号 
            */
            PluginResult pluginResult = new PluginResult();
            pluginResult.Status = Status.Continue;
            string userid = args.Length == 0 ? xinkenArgs.UserId : args[0].ToString();
            string sn = SpiPcbs.m_barcodeList.Count > 0 ? SpiPcbs.m_barcodeList[0].strBarcode : "";
            string guid = GetGuid(sn);

            string stationId = bDual ? xinkenArgs.StationId1 : xinkenArgs.StationId;
            string stationName = bDual ? xinkenArgs.StationName1 : xinkenArgs.StationName;
            object data = new
            {
                HEAD = new
                {
                    H_GUID = guid,
                    H_SRC_SYS = new string[] { "Dezhong-Spi", Version.ToString() },
                    H_OP = "MesCheckFlow",
                    H_TOKEN = xinkenArgs.Token,
                    H_ACTION = stationId
                },
                MAIN = new
                {
                    G_OP_LINE = xinkenArgs.LineName,
                    G_WS = stationName,
                    G_USER = userid,
                    G_OP_PC = xinkenArgs.FixtureId,
                    G_SN = sn,
                    G_STATION = stationName,
                    G_Fixture = xinkenArgs.FixtureId,
		            G_Params = SpiPcbs.pcb_name,
		            G_SIDE = xinkenArgs.G_SIDE,
                    G_StencilSN = xinkenArgs.G_StencilSN,
		            G_SqueegeeSN = xinkenArgs.G_SqueegeeSN,
		            G_SPSN = xinkenArgs.G_SPSN,
                }
            };
            string jsonDataStr = JsonHelper.Serialize(data);
            Log(string.Format("进站检查 参数:{0} ", jsonDataStr));
            string resStr = httpHelper.Post(xinkenArgs.MesUrl, jsonDataStr);
            Log(string.Format("Mes 返回:{0} ", resStr));
            XinkenMesRes res = JsonHelper.DeserializeByStr<XinkenMesRes>(resStr);
            if(res == null)
            {
                pluginResult.Status = Status.Alarm;
                pluginResult.ErrorMsg = "MES返回序列化失败";
                return pluginResult;
            }
            if (res.HEAD.H_GUID.Equals(guid))
            {
                if (res.HEAD.H_RET.Equals("00001"))
                {
                    pluginResult.Status = Status.Continue;
                    pluginResult.ErrorMsg = "";
                    Log(string.Format("GUID:{0} sn:{1} 允许测试", guid, sn));
                }
                else
                {
                    pluginResult.Status = Status.Alarm;
                    pluginResult.ErrorMsg = string.Format("请求测试失败，Mes返回错误代码:[{0}] 错误信息:[{1}]", res.HEAD.H_RET, res.HEAD.H_MSG);
                    Log(pluginResult.ErrorMsg);
                }
            }
            else
            {
                pluginResult.Status = Status.Alarm;
                pluginResult.ErrorMsg = string.Format("进板GUID和Mes返回不一致，请检查Mes的GUID:[{0}]", res.HEAD.H_GUID);
                Log(string.Format("productIn 进板GUID:{0}和Mes GUID:{1}", guid, res.HEAD.H_GUID));
            }
            return pluginResult;
        }

        public PluginResult AfterProductIn(ref SpiPcbs SpiPcbs, bool bDual = false, params object[] args)
        {
            Log("AfterProductIn");
            return new PluginResult();
        }
        public PluginResult BeforeProductOut(ref SpiPcbs SpiPcbs, bool bDual = false, params object[] args)
        {
            Log("BeforeProductOut");
            return new PluginResult();
        }

        public PluginResult ProductOut(ref SpiPcbs SpiPcbs, bool bDual = false, params object[] args)
        {
            Log("ProductOut");
            PluginResult pluginResult = new PluginResult();
            pluginResult.Status = Status.Continue;
            pluginResult.ErrorMsg = "";
            XinkenMesRes res;
            string userid = args.Length == 0 ? xinkenArgs.UserId : args[0].ToString();
            string sn = SpiPcbs.m_barcodeList.Count > 0 ? SpiPcbs.m_barcodeList[0].strBarcode : "";
            string stationId = bDual ? xinkenArgs.StationId1 : xinkenArgs.StationId;
            string stationName = bDual ? xinkenArgs.StationName1 : xinkenArgs.StationName;
            string guid = GetGuid(sn);
            object postData;
            try
            {
                if (SpiPcbs.is_error == 0) // ok 请求过战
                {
                    postData = new
                    {
                        HEAD = new
                        {
                            H_GUID = guid,
                            H_SRC_SYS = new string[] { "Dezhong-Spi", Version.ToString() },
                            H_OP = "MesUpdateInfo",
                            H_TOKEN = xinkenArgs.Token,
                            H_ACTION = stationId,
                        },
                        MAIN = new
                        {
                            G_OP_LINE = xinkenArgs.LineName,
                            G_WS = stationName,
                            G_USER = userid,
                            G_OP_PC = xinkenArgs.FixtureId,
                            G_SN = sn,
                            G_STATION = stationName,
                            G_Code = "0",
                            G_ErrMsg = "hello mes",
                            TestResult = GetOkTestResult(SpiPcbs),
                            G_ImageFiles = "",
                            G_SIDE = xinkenArgs.G_SIDE,
                            G_StencilSN = xinkenArgs.G_StencilSN,
                            G_SqueegeeSN = xinkenArgs.G_SqueegeeSN,
                            G_SPSN = xinkenArgs.G_SPSN,
                        }
                    };
                }
                else // ng请求过战
                {
                    postData = new
                    {
                        HEAD = new
                        {
                            H_GUID = guid,
                            H_SRC_SYS = new string[] { "Dezhong-Spi", Version.ToString() },
                            H_OP = "MesUpdateInfo",
                            H_TOKEN = xinkenArgs.Token,
                            H_ACTION = stationId,
                        },
                        MAIN = new
                        {
                            G_OP_LINE = xinkenArgs.LineName,
                            G_WS = stationName,
                            G_USER = userid,
                            G_OP_PC = xinkenArgs.FixtureId,
                            G_SN = sn,
                            G_STATION = stationName,
                            G_ErrCode = "1",
                            G_ErrMsg = "It's so sad, a bad board",
                            TestResult = GetNgTestResult(SpiPcbs),
                            G_ImageFiles = GetNgImageRes(SpiPcbs),
                            G_SIDE = xinkenArgs.G_SIDE,
                            G_StencilSN = xinkenArgs.G_StencilSN,
                            G_SqueegeeSN = xinkenArgs.G_SqueegeeSN,
                            G_SPSN = xinkenArgs.G_SPSN,
                        }
                    };
                }
                string jsonDataStr = JsonHelper.Serialize(postData);
                Log(string.Format("进站检查 参数:{0} ", jsonDataStr));
                string resStr = httpHelper.Post(xinkenArgs.MesUrl, jsonDataStr);
                Log(string.Format("Mes 返回:{0} ", resStr));
                res = JsonHelper.DeserializeByStr<XinkenMesRes>(resStr);
                if (res != null && res.HEAD.H_GUID.Equals(guid))
                {
                    if (res.HEAD.H_RET.Equals("00001"))
                    {
                        Log(string.Format("GUID:{0} sn:{1} 允许过站", guid, sn));
                        pluginResult.Status = Status.Continue;
                        pluginResult.ErrorMsg = "";
                    }
                    else
                    {
                        pluginResult.Status = Status.Alarm;
                        pluginResult.ErrorMsg = string.Format("GUID:{0} sn:{1} 请求过站失败", guid, sn);
                        Log(pluginResult.ErrorMsg);
                    }
                }
                else if(res !=null)
                {
                    pluginResult.Status = Status.Alarm;
                    pluginResult.ErrorMsg = string.Format("productOut 进板GUID:{0}和Mes GUID:{1}", guid, res.HEAD.H_GUID);
                    Log(pluginResult.ErrorMsg);
                }
            }
            catch (Exception er)
            {
                pluginResult.Status = Status.Alarm;
                pluginResult.ErrorMsg = string.Format("sn:{0} 请求过站失败 {1}", sn, er.Message);
                Log(pluginResult.ErrorMsg, er);
            }
            return pluginResult;
        }

        public PluginResult AfterProductOut(ref SpiPcbs SpiPcbs, bool bDual = false, params object[] args)
        {
            Log("AfterProductOut");
            return new PluginResult();
        }

        public PluginResult Done(ref SpiPcbs SpiPcbs, bool bDual = false, params object[] args)
        {
            Log("Done");
            return new PluginResult();
        }

        public void OpenSettingForm(params object[] args)
        {
            Init();
            new Setting(xinkenArgs).ShowDialog();     
        }

        private void Log(string msg, Exception er = null)
        {
            if (xinkenArgs.LogEnable)
            {
                if (er == null) LogHelper.WriteLog(msg);
                else LogHelper.WriteLog(msg, er); ;
            }
        }

        /// <summary>
        /// 获取guid
        /// </summary>
        /// <returns></returns>
        private string GetGuid(string sn)
        {
            string guid = Guid.NewGuid().ToString("D");
            if (!sn.Equals(""))
            {
                var one = guidList.Find(v => v.Key.Equals(sn));
                if (one.Value != null && one.Key != null)
                {
                    guid = one.Value;
                }
                else
                {
                    if (guidList.Count < xinkenArgs.SaveSnCount)
                        guidList.Add(new KeyValuePair<string, string>(sn, guid));
                    else
                    {
                        guidList.RemoveAt(0);
                        guidList.Add(new KeyValuePair<string, string>(sn, guid));
                    }
                }
            }
            return guid;
        }

        /// <summary>
        /// 拼接ok子板
        /// </summary>
        /// <returns></returns>
        private string GetOkTestResult(SpiPcbs SpiPcbs)
        {
            //"TestResult":"测试程序名,测试条码_拼板号,测试日期（月日年）,时间（时分秒）,拼板数,no,no,拼板号,pass,True,pass,pass（多笔数据用$$$分割）
            string res = "";
            var pcb = SpiPcbs;
            for (int i = 0; i < pcb.pcb_childen_number; i++)
            {
                string pars = "{0},{1}_{5},{2},{3},{4},no,no,{5},pass,True,pass,pass";
                if (i > 0) pars = "$$$" + pars;
                res += string.Format(pars,
                    pcb.pcb_name,
                    pcb.pcb_number,
                    pcb.create_time.ToString("MM/dd/yyyy"),
                    pcb.create_time.ToString("HH:mm:ss"),
                    pcb.pcb_childen_number,
                    i + 1);
            }
            return res;
        }
        /// <summary>
        /// 拼接ng子板
        /// </summary>
        /// <returns></returns>
        private string GetNgTestResult(SpiPcbs SpiPcbs)
        {
            //"TestResult":"0测试程序名,1测试条码_7拼板号,2测试日期,3时间（时分秒）,4拼板数,5不良位号,6不良位号的料号，
            //7拼板号,8不良类型, FAULT, FAIL, 9不良类型
            //$$$测试条码_拼板号,测试日期,时间（时分秒）,拼板数,不良位号,不良位号的料号，拼板号,不良类型, FAULT, FAIL, 不良类型
            string res = "";
            var pcb = SpiPcbs;
            var result = SpiPcbs.results;
            for (int i = 0; i < result.Count; i++)
            {
                var data = result[i];

                if (!data.IsError()) continue;
                string pars = "{0},{1}_{7},{2},{3},{4},{5},{6},{7},{8},FAULT,FAIL,{9}";
                if (i > 0) pars = "$$$" + pars;
                tagBarcodeInfo barcodeInfo = SpiPcbs.m_barcodeList.Find(u => u.subBoard == data.sub_board && u.FunctionType == 0);
                res += string.Format(pars,
                    pcb.pcb_name.Replace(",", ""),
                    pcb.pcb_number.Replace(",", ""),
                    pcb.create_time.ToString("MM/dd/yyyy"),
                    pcb.create_time.ToString("HH:mm:ss"),
                    pcb.pcb_childen_number,
                    data.part_name.Replace(",", ""),
                    data.part_number.Replace(",", ""),
                    data.sub_board,
                    data.ErrStr(" "),
                    data.ErrStr(" ")
                    );
            }
            return res;
        }

        /// <summary>
        /// 获取ng图片地址
        /// </summary>
        /// <returns></returns>
        private string GetNgImageRes(SpiPcbs SpiPcbs)
        {
            //"TestResult":"0测试程序名,1测试条码_7拼板号,2测试日期,3时间（时分秒）,4拼板数,5不良位号,6不良位号的料号，
            //7拼板号,8不良类型, FAULT, FAIL, 9不良类型
            //$$$测试条码_拼板号,测试日期,时间（时分秒）,拼板数,不良位号,不良位号的料号，拼板号,不良类型, FAULT, FAIL, 不良类型
            string res = "";
            var pcb = SpiPcbs;
            var result = SpiPcbs.results;
            for (int i = 0; i < result.Count; i++)
            {
                var data = result[i];
                string pars = "{0}{1}";
                if (i > 0) pars = "$$$" + pars;
                res += string.Format(pars,
                    pcb.pcb_path.Replace("\\", "/").Replace(",", ""),
                    data.part_image_path.Replace("\\", "/").Replace(",", "")
                    );
            }
            return res;
        }

        public void Dispose()
        {

        }
    }
}
